package org.hako.recite.word.test.impl.gui.swt;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.hako.recite.word.test.impl.gui.WordTestBehavior;

/**
 * Abstract implement of shell in application.
 * 
 * @since 0.4.3
 * @author <a href="mailto:xnnyygn@gmail.com">xnnyygn</a>
 */
public abstract class AbstractReciteWordShell {

	private Display display = Display.getDefault();
	protected Shell shell;
	protected WordTestBehavior behavior;

	/**
	 * Create
	 * 
	 * @param style
	 *            style of shell
	 * @param behavior
	 */
	public AbstractReciteWordShell(int style, WordTestBehavior behavior) {
		super();
		this.behavior = behavior;
		initializeAsTopShell(style);
	}

	/**
	 * Create top shell. Top shell meaning shell with display, no parent shell.
	 * 
	 * @param style
	 */
	private void initializeAsTopShell(int style) {
		shell = new Shell(display, style);
	}

	/**
	 * Create
	 * 
	 * @param parentShell
	 * @param style
	 * @param behavior
	 */
	public AbstractReciteWordShell(Shell parentShell, int style,
			WordTestBehavior behavior) {
		super();
		this.behavior = behavior;
		if (parentShell == null) {
			initializeAsTopShell(style);
		} else {
			shell = new Shell(parentShell, style);
			disableCloseDispose();
			disableEscDispose();
		}
	}

	/**
	 * Disable function that click close to dispose
	 */
	private void disableCloseDispose() {
		shell.addListener(SWT.Close, new Listener() {

			@Override
			public void handleEvent(Event event) {
				shell.setVisible(false);
				event.doit = false;
			}
		});
	}

	/**
	 * Disable function that press ESC to dispose
	 */
	private void disableEscDispose() {
		shell.addTraverseListener(new TraverseListener() {

			@Override
			public void keyTraversed(TraverseEvent e) {
				if (e.detail == SWT.TRAVERSE_ESCAPE) {
					e.doit = false;
				}
			}
		});
	}

	/**
	 * Show shell. ATTENTION, if you create a shell without parent shell, do not
	 * invoke this method more than 1 time.
	 * 
	 * @see Shell#open()
	 */
	public void show() {
		shell.open();
		if (display != null) {
			while (!shell.isDisposed()) {
				if (!display.readAndDispatch()) {
					display.sleep();
				}
			}
			display.dispose();
		}
	}

	/**
	 * Hide shell.
	 * 
	 * @see Shell#setVisible(boolean)
	 */
	public void hide() {
		shell.setVisible(false);
	}

	/**
	 * Make the shell center in the client area.
	 */
	public void center() {
		Rectangle clientArea = display.getClientArea();
		int left = (clientArea.width - shell.getSize().x) / 2;
		int top = (clientArea.height - shell.getSize().y) / 2;
		shell.setLocation(left, top);
	}

	/**
	 * Get shell.
	 * 
	 * @return the shell
	 */
	Shell getShell() {
		return shell;
	}

}
